Ext.data.ProxyMgr.registerType("IOrders.proxy.clientOrdersDBProxy",
    Ext.extend(Ext.data.Proxy, {
        create: function(operation, callback, scope) {
            operation.setStarted();
            clientDataSync.db.transaction(function (transaction) {
                var recs = operation.records;
                for(var i = 0; i < recs.length; i++) {
                    var rec = recs[i];
                    transaction.executeSql(
                        'insert into SaleOrder (customer, toDate, isCredit, isDocuments) values(?, ?, ?, ?)',
                        [rec.get('customer'), rec.get('toDate'), rec.get('isCredit'), rec.get('isDocuments')],
                        function(transaction, resultSet) {
                            if (!resultSet.rowsAffected) {
                                // Previous insert failed. Bail.
                                concsole.log('No rows affected!');
                                return false;
                            }
                            rec.set('id', resultSet.insertId);
                            operation.setCompleted();
                            operation.setSuccessful();
                            //finish with callback
                            if (typeof callback == 'function') {
                                callback.call(scope || thisProxy, operation);
                            }
                            return true;
                        }, errorHandler
                    );
                }
            });
        },
        read: function(operation, callback, scope) {
            var thisProxy = this;
            var clientOrders = [];
            clientDataSync.db.transaction(function (transaction) { 
            transaction.executeSql(
                'select so.id, so.toDate, so.isCredit, so.isDocuments, c.id customer_id, c.name customer,  tp.totalPrice ' + 
                    'from SaleOrder so '+
                        'join Customer c on c.id = so.customer '+
                        'join (select saleOrder, sum(price * rel * volume) totalPrice from SaleOrderPosition sop group by saleOrder) tp on tp.saleOrder = so.id ' +
                    (operation.filter ? 'where so.customer = ?' : ''),
                operation.filter ? [operation.filter.client] : [],
                function(t, result) {
                        var rows = result.rows;
                        for(var i = 0; i < rows.length; i++) {
                            var it = new thisProxy.model(rows.item(i));
                            it.set('totalPrice', it.get('totalPrice').toFixed(2));
                            clientOrders.push(it);
                        }
                        operation.resultSet = new Ext.data.ResultSet({
                            records: clientOrders,
                            total  : clientOrders.length,
                            loaded : true
                        });
                        operation.setSuccessful();
                        operation.setCompleted();
                        if (typeof callback == "function") {
                            callback.call(scope || thisProxy, operation);
                        }
                }, errorHandler);
            });
        },
        update: function(operation, callback, scope) {
            clientDataSync.db.transaction(function (transaction) {
                var recs = operation.records;
                for(var i = 0;i < recs.length; i++) {
                    var rec = recs[i];
                    transaction.executeSql(
                        'update SaleOrder set isCredit = ?, isDocuments = ? where id = ?',
                        [rec.get('isCredit'), rec.get('isDocuments'), rec.getId()]
                    );
                }
                operation.setCompleted();
                operation.setSuccessful();
                if (typeof callback == 'function') {
                    callback.call(scope || thisProxy, operation);
                }
            });
        },
        destroy: function(operation, callback, scope) {
        }
    })
);

Ext.data.ProxyMgr.registerType("IOrders.proxy.clientDBProxy",
    Ext.extend(Ext.data.Proxy, {
        create: function(operation, callback, scope) {
        },
        read: function(operation, callback, scope) {
            var thisProxy = this;
            var clients = [];
            clientDataSync.db.transaction(function (transaction) { 
            transaction.executeSql(
                'select c.id, c.name, c.address, w.name warehouse from Customer c ' +
                    'join Warehouse w on w.id = c.warehouse', [],
                function(t, result) {
                        var rows = result.rows;
                        for(var i = 0; i < rows.length; i++) {
                            clients.push(new thisProxy.model(rows.item(i)));
                        }
                        operation.resultSet = new Ext.data.ResultSet({
                            records: clients,
                            total  : clients.length,
                            loaded : true
                        });
                        operation.setSuccessful();
                        operation.setCompleted();
                        if (typeof callback == "function") {
                            callback.call(scope || thisProxy, operation);
                        }
                }, errorHandler);
            });
        },
        update: function(operation, callback, scope) {
        },
        destroy: function(operation, callback, scope) {
        }
    })
);

Ext.data.ProxyMgr.registerType("IOrders.proxy.orderPositionDBProxy",
    Ext.extend(Ext.data.Proxy, {
        create: function(operation, callback, scope) {
        },
        read: function(operation, callback, scope) {
            var thisProxy = this;
            var products = [];
            if(operation.filter.loadForCreate) {
                clientDataSync.db.transaction(function (transaction) {
                    transaction.executeSql(
                        'select  p.id, p.name, p.firstName, p.rel, p.factor, o.price, o.dateSinceOrder, s.level ' +
                        'from Product p ' +
                            'join Customer c on c.id = ? ' +
                            'join Offer o on o.customer = c.id and o.product = p.id ' +
                            'join Stock s on s.product = p.id and s.warehouse = c.warehouse and s.level > 0 ' +   
                        'where p.category = ?',
                        [operation.filter.customer, operation.filter.category],
                        function(t, result) {
                                var rows = result.rows;
                                for(var i = 0; i < rows.length; i++) {
                                    var it = Ext.apply({productcategory_id: operation.filter.category}, rows.item(i));
                                    it.name = it.name.replace(it.firstName, '');
                                    it.firstName = it.firstName.replace('.', '');
                                    it.isActive = it.dateSinceOrder ? true : false;
                                    products.push(new thisProxy.model(it));
                                }
                                operation.resultSet = new Ext.data.ResultSet({
                                        records: products,
                                        total  : products.length,
                                        loaded : true
                                    });
                                    operation.setSuccessful();
                                    operation.setCompleted();
                                    if (typeof callback == "function") {
                                        callback.call(scope || thisProxy, operation);
                                    }
                            }, errorHandler
                        );
                });
            } else if(operation.filter.loadOne) {
                clientDataSync.db.transaction(function (transaction) {
                        transaction.executeSql(
                            'select  p.id, p.name, p.firstName, p.rel, p.factor, o.dateSinceOrder, s.level, sop.id sopId, ' +
                                'case when sop.volume is null then 0 else sop.volume end as volume, ' +
                                'case when sop.price is null then o.price else sop.price end as price ' +
                            'from Product p ' +
                                'join Customer c on c.id = ? ' +
                                'join Offer o on o.customer = c.id and o.product = p.id ' +
                                'join Stock s on s.product = p.id and s.warehouse = c.warehouse and s.level > 0 ' +
                                (operation.filter.onlyInOrder ? '' : 'left ') +'join SaleOrderPosition sop on sop.saleOrder = ? and sop.product = o.product ' +
                            'where p.category = ?',
                            [operation.filter.customer, operation.filter.saleOrder,operation.filter.category],
                            function(t, result) {
                                if (result.rows.length){
                                    var rows = result.rows;
                                    for(var i = 0; i < rows.length; i++) {
                                        var it = Ext.apply({productcategory_id: operation.filter.category}, rows.item(i));
                                        it.name = it.name.replace(it.firstName, '');
                                        it.firstName = it.firstName.replace('.', '');
                                        it.isActive = it.dateSinceOrder || it.volume ? true : false;
                                        products.push(new thisProxy.model(it));
                                    }
                                    operation.resultSet = new Ext.data.ResultSet({
                                        records: products,
                                        total  : products.length,
                                        loaded : true
                                    });
                                    operation.setSuccessful();
                                    operation.setCompleted();
                                    if (typeof callback == "function") {
                                        callback.call(scope || thisProxy, operation);
                                    }
                                }
                        }, errorHandler
                    );
                });
            }
        },
        update: function(operation, callback, scope) {
            operation.setStarted();
            var thisProxy = this;
            clientDataSync.db.transaction(function (transaction) {
                var recs = operation.records;
                for(var i = 0;i < recs.length; i++) {
                    var rec = recs[i];
                    if(!rec.get('sopId')) {
                        rec.get('volume') > 0 && transaction.executeSql(
                            'INSERT OR IGNORE INTO SaleOrderPosition(saleOrder, product, volume, price, rel) VALUES (?, ?, ?, ?, ?)',
                            [operation.params.saleOrder, rec.getId(), rec.get('volume'), rec.get('price'), rec.get('rel')],
                            function(t, resultSet) {
                                if (!resultSet.rowsAffected) {
                                    // Previous insert failed. Bail.
                                    concsole.log('No rows affected!');
                                    return false;
                                }
                                rec.set('sopId', resultSet.insertId);
                                return true;
                            }, errorHandler
                        );
                    } else {
                        if(rec.get('volume') > 0) {
                            transaction.executeSql(
                                'update SaleOrderPosition set volume = ? where rel = ? and saleOrder = ? and product = ?',
                                [rec.get('volume'), rec.get('rel'), operation.params.saleOrder, rec.getId()],
                                function(t, result) {}, errorHandler
                            );
                        } else {
                            transaction.executeSql(
                                'delete from SaleOrderPosition where saleOrder = ? and product = ?',
                                [operation.params.saleOrder, rec.getId()],
                                function(t, result) {}, errorHandler
                            );
                        }
                    }
                    rec.set('volume', 0);
                    rec.set('isActive', false);
                }
                operation.setCompleted();
                operation.setSuccessful();
                if (typeof callback == "function") {
                    callback.call(scope || thisProxy, operation);
                }
            });
        },
        destroy: function(operation, callback, scope) {
        },
        batch: function(operations, listeners) {
            var batch = new Ext.data.Batch({
                proxy: this,
                listeners: listeners || {}
            });            
            Ext.each(this.batchOrder.split(','), function(action) {
                if (operations[action]) {
                    batch.add(new Ext.data.Operation({
                        action : action, 
                        records: operations[action].recs,
                        params: operations[action].params
                    }));
                }
            }, this);            
            batch.start();            
            return batch;
        }
    })
);

Ext.data.ProxyMgr.registerType("IOrders.proxy.productCategoryDBProxy",
    Ext.extend(Ext.data.Proxy, {
        create: function(operation, callback, scope) {
        },
        read: function(operation, callback, scope) {
            var thisProxy = this;
            var procCategories = [];
            var args = [operation.filter.customer];
            operation.filter.onlyInOrder && args.push(operation.filter.saleOrder);
            clientDataSync.db.transaction(function (transaction) {
            transaction.executeSql(
                'select distinct c.id, c.name, c.ord, c.packageName from Category c ' +
                    'join Product p on p.category = c.id ' +
                    'join Customer cus on cus.id = ? ' +
                    'join Offer o on o.product = p.id and o.customer = cus.id ' +
                    'join Stock s on s.product = p.id and s.warehouse = cus.warehouse and s.level > 0 ' +
                    (operation.filter.onlyInOrder ? 'join SaleOrderPosition sop on sop.product = p.id and sop.saleOrder = ?' : ''),
                args,
                function(t, result) {
                        var rows = result.rows;
                        for(var i = 0; i < rows.length; i++) {
                            var prodCategory = new thisProxy.model(rows.item(i));
                            procCategories.push(prodCategory);
                        }
                        operation.resultSet = new Ext.data.ResultSet({
                            records: procCategories,
                            total  : procCategories.length,
                            loaded : true
                        });
                        operation.setSuccessful();
                        operation.setCompleted();
                        if (typeof callback == "function") {
                            callback.call(scope || thisProxy, operation);
                        }
                }, errorHandler);
            });
        },
        update: function(operation, callback, scope) {
        },
        destroy: function(operation, callback, scope) {
        }
    })
);

IOrders.models.Client = Ext.regModel('Client', {
    fields: ['id', 'name', 'address', 'cls', 'warehouse'],
    proxy: {
        type: 'IOrders.proxy.clientDBProxy'
    }
});

IOrders.models.Order = Ext.regModel('Order', {
    fields: ['id', 'cls', 'toDate', 'isDocuments', 'isCredit', 'totalPrice', 'customer', 'customer_id'],
    proxy: {
        type: 'IOrders.proxy.clientOrdersDBProxy'
    }
});

IOrders.models.ProductCategory = Ext.regModel('ProductCategory', {
    fields: ['id', 'name', 'isInactive', 'cls', 'packageName', 'totalPrice'],
    hasMany: {
        name: 'products', model: 'Product',
        storeConfig: {
            sorters: 'firstName',
            getGroupString : function(record) {
                return record.get('firstName');
            },
                sync: function(params) {
                    var me        = this,
                        options   = {},
                        toCreate  = me.getNewRecords(),
                        toUpdate  = me.getUpdatedRecords(),
                        toDestroy = me.getRemovedRecords(),
                        needsSync = false;   
                    if (toCreate.length > 0) {
                        options.create = {recs: toCreate, params: params};
                        needsSync = true;
                    }    
                    if (toUpdate.length > 0) {
                        options.update = {recs: toUpdate, params: params};
                        needsSync = true;
                    }    
                    if (toDestroy.length > 0) {
                        options.destroy = {recs: toDestroy, params: params};
                        needsSync = true;
                    }    
                    if (needsSync && me.fireEvent('beforesync', options) !== false) {
                        me.proxy.batch(options, me.getBatchListeners());
                    }
                }
        }
    },
    proxy: {
        type: 'IOrders.proxy.productCategoryDBProxy'
    }
});

IOrders.models.Product = Ext.regModel('Product', {
    fields: ['id', 'isActive', 'dateSinceOrder', 'firstName', 'name', 'level', 'cls', 'price', 'factor', 'volume', 'productcategory_id', 'sopId'],
    belongsTo: 'ProductCategory',
    proxy: {
        type: 'IOrders.proxy.orderPositionDBProxy'
    }
});

IOrders.stores.clientStore = new Ext.data.Store({
    storeId: 'clientStore',
    model  : 'Client',
    sorters: 'name',
    getGroupString : function(record) {
        return record.get('name')[0];
    }
});

Ext.namespace('IOrders.lib.maps');

IOrders.lib.maps.clearOverlays = function(map) {
  if (map.markersArray) {
    for (var i = 0; i < map.markersArray.length; i++) {
        map.markersArray[i].setMap(null);
    }
  }
}

IOrders.lib.maps.addMarker = function(marker, map) {
    map.markersArray || (map.markersArray = []);  
    map.markersArray.push(marker);
}

IOrders.lib.maps.addLayer = function(layerName, layer, map) {
    map.layers || (map.layers = {});
    if(!map.layers[layerName]) {
        layer.setMap(map);
        map.layers[layerName] = layer;
    }
}

IOrders.lib.maps.geocoder = new google.maps.Geocoder();